//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>

#define THREADAMOUNT        100

EXTERN void DzYield();

DzMutex   g_finishCodeMutex;

Int32 FinishedCodeThread01(void *pvPara)
{

    g_finishCodeMutex.Lock();

    DzYield();

    g_finishCodeMutex.Unlock();

    return NOERROR;
}

EXTERN void GetThreadFinishCode()
{
    IThread     *pIThread[THREADAMOUNT];
    ECode     ec;
    uint_t      i;
    Int32         nFinishCode;

    g_finishCodeMutex.Lock();
    for (i = 0; i < THREADAMOUNT; i++) {
        ec = DzCreateKernelThread(FinishedCodeThread01, (void *)0, 0,
                                (ThreadPriorityRank)0xFFFFEEEE, &pIThread[i]);

        if (FAILED(ec)) {
            kprintf("Create thread %d failed, the ec = 0x%08x\n", i, ec);

            return;
        }

        DzYield();
    }

    for (i = 0; i < THREADAMOUNT; i++) {
        ec = pIThread[i]->GetExitCode(&nFinishCode);
        assert(E_FAIL == ec);
    }

    g_finishCodeMutex.Unlock();

    for (i = 0; i < THREADAMOUNT; i++) {
        pIThread[i]->Join(INFINITE);
    }

    for (i = 0; i < THREADAMOUNT; i++) {
        ec = pIThread[i]->GetExitCode(&nFinishCode);
        assert(NOERROR == ec);
        assert(NOERROR == nFinishCode);
    }

    for (i = 0; i < THREADAMOUNT; i++) {
        ec = pIThread[i]->GetExitCode(NULL);
        assert(E_INVALID_ARGUMENT == ec);
    }

    for (i = 0; i < THREADAMOUNT; i++) {
        pIThread[i]->Release();
    }
}

Int32 ReturnFinishCode(void *pvPara)
{
    return (ECode)pvPara;
}

EXTERN void GetThreadAllFinishCode()
{
    IThread     *pIThread[THREADAMOUNT];
    uint_t      uBaseFinishCode = 0;
    uint_t      uFinishCode;
    Int32       nReturnCode;
    ECode       ec;
    uint_t      i;

    do {
        uFinishCode = uBaseFinishCode;

        for (i = 0; i < THREADAMOUNT; i++) {
            ec = DzCreateKernelThread(ReturnFinishCode, (void *)uFinishCode,
                            0, (ThreadPriorityRank)0xFFFFEEEE, &pIThread[i]);

            if (FAILED(ec)) {
                kprintf("Create thread %d failed, the ec = 0x%08x\n", i, ec);

                return;
            }

            uFinishCode += 0x3;
        }

        uFinishCode = uBaseFinishCode;

        for (i = 0; i < THREADAMOUNT; i++) {
            pIThread[i]->Join(INFINITE);
            ec = pIThread[i]->GetExitCode(&nReturnCode);
            assert(NOERROR == ec);
            assert(uFinishCode == (uint_t)nReturnCode);
            uFinishCode += 0x3;
            pIThread[i]->Release();
        }

        uBaseFinishCode += 0x10000000;
    } while (uBaseFinishCode <= 0xE0000000);

    uFinishCode = (uint_t)-1;

    for (i = 0; i < THREADAMOUNT; i++) {
        ec = DzCreateKernelThread(ReturnFinishCode, (void *)uFinishCode,
                        0, (ThreadPriorityRank)0xFFFFEEEE, &pIThread[i]);

        if (FAILED(ec)) {
            kprintf("Create thread %d failed, the ec = 0x%08x\n", i, ec);

            return;
        }

        uFinishCode -= 0x3;
    }

    uFinishCode = (uint_t)-1;

    for (i = 0; i < THREADAMOUNT; i++) {
        pIThread[i]->Join(INFINITE);
        ec = pIThread[i]->GetExitCode(&nReturnCode);
        assert(NOERROR == ec);
        assert(uFinishCode == (uint_t)nReturnCode);
        uFinishCode -= 0x3;
        pIThread[i]->Release();
    }
}

EXTERN void AbortThreadGetFinishCode()
{
    IThread         *pIThread;
    ECode           ec;
    Int32           nReturnCode;
    ThreadState     thdState;

    g_finishCodeMutex.Lock();
    ec = DzCreateKernelThread(FinishedCodeThread01, (void *)0, 0,
                    (ThreadPriorityRank)0xFFFFEEEE, &pIThread);
    if (FAILED(ec)) {
        kprintf("Create thread failed, the ec = 0x%08x\n", ec);

        return;
    }

    ec = pIThread->GetState(&thdState);
    assert(NOERROR == ec);
    assert(ThreadState_Running == thdState);

    ec = pIThread->Abort();
    assert(NOERROR == ec);

    g_finishCodeMutex.Unlock();

    ec = pIThread->GetExitCode(&nReturnCode);
    assert(NOERROR == ec);
    assert(E_FAIL == nReturnCode);

    pIThread->Release();
}
